import { WidgetBaseTextSession } from './base'
import { fromAny, BoolValue, FloatValue, StringValue, toAny } from '../../proto'
import { Message } from 'protobufjs'
export class WidgetFileUploaderSession extends WidgetBaseTextSession {
    private uploader: HTMLInputElement
    constructor(render: HTMLElement) {
        super('FileUploader', render)
    }
    createWidget(...argv): HTMLElement {
        this.uploader = document.createElement('input')
        this.uploader.type = 'file'
        return this.uploader
    }
    onReceive(name: String, sessionId: number, futureId: number, ...argv) {
        switch (name) {
            case 'getMimeType':
                return this.getMimeType(sessionId, futureId)
            case 'setMimeType':
                return this.setMimeType(...argv)
            case 'getFilename':
                return this.getFilename(sessionId, futureId)
            case 'upload':
                return this.upload(sessionId, futureId, ...argv)
        }
        super.onReceive(name, sessionId, futureId, ...argv);
    }
    private getMimeType(sessionId: number, futureId: number) {
        const mimeType = toAny(this.uploader.accept, StringValue)
        this.onGetMimeType(sessionId, futureId, mimeType)
    }
    private onGetMimeType(sessionId: number, futureId: number, mimeType: Message) {
        this.sendAction('onGetMimeType', sessionId, futureId, mimeType)
    }
    private setMimeType(...argv) {
        this.uploader.accept = fromAny(argv[0], StringValue)
    }
    private getFilename(sessionId: number, futureId: number) {
        if (!this.uploader.files || this.uploader.files.length < 1)
            throw new Error('You have not selected a file yet.')
        const file = this.uploader.files[0]
        const filename = toAny(file.name, StringValue)
        this.onGetFilename(sessionId, futureId, filename)
    }
    private onGetFilename(sessionId: number, futureId: number, filename: Message) {
        this.sendAction('onGetFilename', sessionId, futureId, filename)
    }
    private upload(sessionId: number, futureId: number, ...argv) {
        if (!this.uploader.files || this.uploader.files.length < 1)
            throw new Error('You have not selected a file yet.')
        const url = fromAny(argv[0], StringValue)
        const xhr = new XMLHttpRequest()
        xhr.open('POST', url, true)
        // 文件上传中持续触发
        xhr.upload.onprogress = (e) => {
            // loaded文件已上传大小，total文件总大小
            const progress = toAny(e.loaded / e.total * 100, FloatValue)
            argv[1] && this.sendCallback(argv[1], progress)
        }
        // 文件上传结束触发
        xhr.onload = () => this.onUpload(sessionId, futureId, toAny(true, BoolValue))
        xhr.onerror = () => this.onError(new Error(xhr.statusText), sessionId, futureId)
        const formData = new FormData()
        formData.append('file', this.uploader.files[0])
        xhr.send(formData)
    }
    private onUpload(sessionId: number, futureId: number, result: Message) {
        this.sendAction('onUpload', sessionId, futureId, result)
    }
    public listenFileSourceChange(onchange: (url: string) => void) {
        this.uploader.onchange = () => {
            const file = this.uploader.files[0]
            const reader = new FileReader()
            reader.onload = () => onchange(reader.result as string)
            reader.readAsDataURL(file)
        }
    }
}